package cn.mf.hrm.service.impl;

import cn.mf.hrm.doc.CourseDoc;
import cn.mf.hrm.dto.CourseESQuery;
import cn.mf.hrm.mapper.HighlightResultMapper;
import cn.mf.hrm.repository.CourseElasticSearchRepository;
import cn.mf.hrm.service.ICourseESService;
import cn.mf.hrm.util.PageList;
import cn.mf.hrm.vo.AggrbucketVo;
import cn.mf.hrm.vo.SearchPageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CourseESServiceImpl implements ICourseESService {

    @Autowired
    private CourseElasticSearchRepository repository;

    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @Autowired
    private ElasticsearchTemplate template;

    /**
     * 添加课程
     * @param course：课程数据
     */
    /**
     * 抽取方法步骤：选中代码--右键--refactor--extract--method
     * @param course：课程数据
     */
    @Override
    public void save(CourseDoc course) {
        repository.save(course);
    }

    /**
     * 查询
     * @param query
     * @return
     */
    @Override
    public PageList search(CourseESQuery query) {
        //1：创建查询的构建器
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        /*2:设置查询*/
        setQuery(query, queryBuilder);

        /*3:设置高亮*/
        setHighlight(queryBuilder);

        /*4:聚合查询*/
        setAggr(queryBuilder);

        //2.调用repository的search方法查询
        //Page<CourseDoc> page = courseElasticsearchRepository.search(builder.build());
        //13：执行查询
        AggregatedPage<CourseDoc> page = template.queryForPage(queryBuilder.build(),CourseDoc.class,highlightResultMapper);

        //聚合的结果
        Aggregations aggregations = page.getAggregations();
        //把结果封装成map
        Map<String,List<AggrbucketVo>> aggrMap = new HashMap<>();
        aggregations.forEach(aggregation -> { //外层循环--gradeName
            //处理一个聚合结果
            //aggregation是一个聚合结果，其中有一个getbuckets是结果集合列表
            List<AggrbucketVo> aggrbucketVoList = new ArrayList<>();
            ((StringTerms)aggregation).getBuckets().forEach(bucket -> {
//                //名字
//                bucket.getKey();
//                //数量
//                bucket.getDocCount();
                //bucket就是结果明细
                AggrbucketVo aggrbucketVo = new AggrbucketVo((String) bucket.getKey(), bucket.getDocCount());
                aggrbucketVoList.add(aggrbucketVo);
            });
            aggrMap.put(aggregation.getName(),aggrbucketVoList);//key是j聚合的名字
        });
        return new SearchPageList(page.getTotalElements(),page.getContent(),aggrMap);
    }

    /**
     * 聚合查询*/
    private void setAggr(NativeSearchQueryBuilder queryBuilder) {
        //等级的聚合
        TermsAggregationBuilder gradeNameAgg = AggregationBuilders.terms("gradeNameAgg").field("gradeName").size(10);
        //机构的聚合
        TermsAggregationBuilder tenantNameAgg = AggregationBuilders.terms("tenantNameAgg").field("tenantName").size(10);
        queryBuilder.addAggregation(gradeNameAgg).addAggregation(tenantNameAgg);
    }

    /**
     * 查询
     * @param query
     * @param queryBuilder
     */
    private void setQuery(CourseESQuery query, NativeSearchQueryBuilder queryBuilder) {
        //2：指定要搜索的索引库
        queryBuilder.withIndices("hrm");
        queryBuilder.withTypes("course");

        //3：分页
        queryBuilder.withPageable(PageRequest.of(query.getPage() - 1,query.getRows()));

        //4：排序
        if(StringUtils.hasText(query.getSortField())){
            String sortField = "saleCount";
            switch (query.getSortField()){
                case "xp": sortField = "onlineTime";break;
                case "xl": sortField = "saleCount";break;
                case "pl": sortField = "commentCount";break;
                case "jg": sortField = "price";break;
                case "rq": sortField = "viewCount";break;
            }
            SortOrder sortOrder = SortOrder.DESC;
            if(StringUtils.hasText(query.getSortType()) && query.getSortType().equalsIgnoreCase("asc")){
                sortOrder = SortOrder.ASC;
            }
            queryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortOrder));
        }

        //5：查询条件，组合查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //6：keyword:关键字查询
        if(StringUtils.hasText(query.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("name",query.getKeyword()));
        }

        //7：courseTypeId ;
        if(null != query.getCourseTypeId()){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId",query.getCourseTypeId()));
        }
        //8：gradeName ;
        if(StringUtils.hasText(query.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName",query.getGradeName()));
        }
        //9：tenantName
        if(StringUtils.hasText(query.getTenantName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("tenantName",query.getTenantName()));
        }
        //10：priceMax;
        if(null != query.getPriceMax()){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(query.getPriceMax()));
        }
        //11：priceMin;
        if(null != query.getPriceMin()){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(query.getPriceMin()));
        }
        //12：添加查询条件
        queryBuilder.withQuery(boolQueryBuilder);
    }

    /**
     * 高亮
     * @param queryBuilder
     */
    private void setHighlight(NativeSearchQueryBuilder queryBuilder) {
        //1:设置高亮字段
        HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
        //2:实现高亮
        queryBuilder.withHighlightFields(field);
    }

}


